/**
 * This file is Copyright © 2008 Software Craftsmen Limited. All Rights Reserved.
 */
package com.softwarecraftsmen.functors;

import org.jetbrains.annotations.NotNull;

public abstract class QuaternaryReturningFunctor<A, B, C, D, R>
{
	@NotNull
	public abstract R closure(@NotNull final A a, final @NotNull B b, final @NotNull C c, final @NotNull D d);

	@NotNull
	public final QuaternaryReturningFunctor<A, B, C, D, R> curry()
	{
		return this;
	}

	@NotNull
	public final TernaryReturningFunctor<A, B, C, R> curry(final @NotNull D d)
	{
		return new TernaryReturningFunctor<A, B, C, R>()
		{
			@NotNull
			public R closure(@NotNull final A a, final @NotNull B b, final @NotNull C c)
			{
				return QuaternaryReturningFunctor.this.closure(a, b, c, d);
			}
		};
	}

	@NotNull
	public final BinaryReturningFunctor<A, B, R> curry(final @NotNull C c, final @NotNull D d)
	{
		return new BinaryReturningFunctor<A, B, R>()
		{
			@NotNull
			public R closure(@NotNull final A a, final @NotNull B b)
			{
				return QuaternaryReturningFunctor.this.closure(a, b, c, d);
			}
		};
	}

	@NotNull
	public final UnaryReturningFunctor<A, R> curry(final @NotNull B b, final @NotNull C c, final @NotNull D d)
	{
		return new UnaryReturningFunctor<A, R>()
		{
			@NotNull
			public R closure(@NotNull final A a)
			{
				return QuaternaryReturningFunctor.this.closure(a, b, c, d);
			}
		};
	}

	@NotNull
	public final NullaryReturningFunctor curry(final @NotNull A a, final @NotNull B b, final @NotNull C c, final @NotNull D d)
	{
		return new NullaryReturningFunctor()
		{
			@NotNull
			public R closure()
			{
				return QuaternaryReturningFunctor.this.closure(a, b, c, d);
			}
		};
	}
}